package com.gitee.wsl.mathematics.matrix.mat3

import com.gitee.wsl.ext.array.DoubleArray
import com.gitee.wsl.ext.array.FloatArray
import com.gitee.wsl.io.dataproxy.DataProxy
import com.gitee.wsl.io.dataproxy.asProxy
import com.gitee.wsl.mathematics.matrix.M
import com.gitee.wsl.mathematics.matrix.MatCopyInitializer
import com.gitee.wsl.mathematics.matrix.MatInitializer
import com.gitee.wsl.mathematics.matrix.N
import com.gitee.wsl.mathematics.matrix.mat2.MutableMat2
import com.gitee.wsl.mathematics.matrix.mat2.MutableMat2f
import com.gitee.wsl.mathematics.matrix.mat2.MutableMatrix2
import com.gitee.wsl.mathematics.vector.vec2.MutableVec2
import com.gitee.wsl.mathematics.vector.vec2.MutableVec2f
import com.gitee.wsl.mathematics.vector.vec3.MutableVec3
import com.gitee.wsl.mathematics.vector.vec3.MutableVec3f
import com.gitee.wsl.mathematics.vector.vec3.Vec3f

class MutableMat3f(m00: Float=0.0f, m01: Float=0.0f, m02: Float=0.0f,
                   m10: Float=0.0f, m11: Float=0.0f, m12: Float=0.0f,
                   m20: Float=0.0f, m21: Float=0.0f, m22: Float=0.0f,
                   override val proxy: DataProxy<Float> =
                       FloatArray(
                          m00, m01, m02,
                          m10, m11, m12,
                          m20, m21, m22).asProxy())
    :Mat3f(proxy = proxy),MutableMatrix3F<Mat3f, Vec3f> {
    constructor(other: Matrix3F<*, *>):this(
        other.m00, other.m01,other.m02,
        other.m10, other.m11,other.m12,
        other.m20, other.m21,other.m22)
    constructor(initializer: MatInitializer<Float>):this(
        initializer(0,0),initializer(0,1),initializer(0,2),
        initializer(1,0),initializer(1,1),initializer(1,2),
        initializer(2,0),initializer(2,1),initializer(2,2)
        )

    override val self
        get() = this

    override val m by lazy{listOf(M[0], M[1],M[2])}

    override val n by lazy {listOf(N[0], N[1],N[2])}

    override fun copy(block: MatCopyInitializer<Float>) = MutableMat3f { i, j->
        this[i,j].block(i,j)
    }

    //override fun createVec(indexRage:IntRange) = createVec(indexRage.toList())

    override fun createVec2(x: Float, y: Float) = MutableVec2f(x,y)

    override fun createMat2(block: (MutableMatrix2<Float, *, *>) -> Unit): MutableMat2f {
        val ret = MutableMat2f()
        block(ret)
        return ret
    }

    override fun createVec(indexes: List<Int>) = MutableVec3f(proxy = proxy.asProxy(indexes))

    override fun create(m00: Float, m01: Float,m02: Float,
                        m10: Float, m11: Float,m12: Float,
                        m20: Float, m21: Float,m22: Float)
            =   MutableMat3f(m00, m01, m02,
                            m10, m11, m12,
                            m20, m21, m22)

    override fun toMutable() = this

    override operator fun M.get(row: Int) = createVec(rowIndexes(row))

    override operator fun N.get(col: Int) = createVec(colIndexes(col))

    companion object{
        val IDENTITY  = identity()

        fun identity()= MutableMat3f(
            1.0f, 0.0f, 0.0f,
            0.0f, 1.0f, 0.0f,
            0.0f, 0.0f, 1.0f
        )
    }
}